using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

namespace SIAIllustrator.Calculator
{
    class IndexCalculator
    {

        public static DataTable CalculateAnnuity(double premium, int month, int beginYear, int endYear,
            double dpartRate, double ppartRate, double guarRate, double amortRate, int defPeriod,
            int payPeriod, int payType, DataTable dt)
        {

            /**************************************************
             *  declare and assign variables needed to
             *  call GuaranteedPayout function at the end of
             *  this function and set the Quote object
             * ***********************************************/

            double zpremium = premium;
            int zpayPeriod = payPeriod;
            int zdefPeriod = defPeriod;
            
            /**************************************************
             *  create DataTable that will hold result data
             * ***********************************************/

            DataTable dtResults = new DataTable();

            DataColumn dc0 = new DataColumn();
            dc0.ColumnName = "#";
            dc0.DataType = Type.GetType("System.Int32");

            DataColumn dc1 = new DataColumn();
            dc1.ColumnName = "Year";
            dc1.DataType = Type.GetType("System.Int32");

            DataColumn dc2 = new DataColumn();
            dc2.ColumnName = "Start Balance";
            dc2.DataType = Type.GetType("System.Double");

            DataColumn dc3 = new DataColumn();
            dc3.ColumnName = "Index";
            dc3.DataType = Type.GetType("System.Double");

            DataColumn dc4 = new DataColumn();
            dc4.ColumnName = "Credited";
            dc4.DataType = Type.GetType("System.Double");

            DataColumn dc5 = new DataColumn();
            dc5.ColumnName = "Interest Earned";
            dc5.DataType = Type.GetType("System.Double");

            DataColumn dc6 = new DataColumn();
            dc6.ColumnName = "Balance";
            dc6.DataType = Type.GetType("System.Double");

            DataColumn dc7 = new DataColumn();
            dc7.ColumnName = "Payment";
            dc7.DataType = Type.GetType("System.Double");

            DataColumn dc8 = new DataColumn();
            dc8.ColumnName = "End Balance";
            dc8.DataType = Type.GetType("System.Double");


            dtResults.Columns.Add(dc0);
            dtResults.Columns.Add(dc1);
            dtResults.Columns.Add(dc2);
            dtResults.Columns.Add(dc3);
            dtResults.Columns.Add(dc4);
            dtResults.Columns.Add(dc5);
            dtResults.Columns.Add(dc6);
            dtResults.Columns.Add(dc7);
            dtResults.Columns.Add(dc8);


            /********************************************************
             *  declare needed variables and calculate annuity
             *  output and populate the datatable
             * *****************************************************/

            double balance = premium;
            int numRows = dt.Rows.Count;
            int year = beginYear + 1;
            int rmonth = 0, ryear = 0;
            double totalbenefit = 0;
            double endbalance = 0;
            double partrate = dpartRate;
            double avgsprate = 0;
            double avgcrate = 0;
            int denom = defPeriod + payPeriod;
            DataRow dr;
            int count = 1;

            foreach (DataRow r in dt.Rows)
            {


                ryear = int.Parse(r[0].ToString());
                rmonth = int.Parse(r[1].ToString());

                if ((rmonth == month) & (ryear == year))
                {

                    dr = dtResults.NewRow();

                    dr["#"] = count;
                    dr["Year"] = year;
                    dr["Start Balance"] = balance;


                    double sprate = double.Parse(r[3].ToString());
                    double crate;

                    dr["Index"] = sprate;

                    if (sprate >= 0)
                        crate = sprate * partrate;
                    else
                        crate = 0;

                    avgsprate += sprate;
                    avgcrate += crate;


                    dr["Credited"] = crate;

                    dr["Interest Earned"] = balance * crate;

                    balance = balance * (1 + crate);

                    dr["Balance"] = balance;

                    /********** deferral period *************/
                    
                    if ((defPeriod == 1) & (payType == 2))
                    {
                        dr["Payment"] = balance;
                        balance = 0;
                        defPeriod--;
                    }
                    else if (defPeriod > 0)
                    {
                        dr["Payment"] = 0;
                        defPeriod--;
                    }


                    /*********** payout period **************/

                    else if ((defPeriod == 0) & (payPeriod > 0))
                    {

                        double benefit;
                        double numerator = amortRate * Math.Pow(1 + amortRate, payPeriod);
                        double denominator = Math.Pow(1 + amortRate, payPeriod) - 1;

                        benefit = balance * (numerator / denominator);

                        dr["Payment"] = benefit;

                        totalbenefit += benefit;

                        balance = balance - benefit;

                        payPeriod--;

                    }
                    

                    if (defPeriod == 0)
                        partrate = ppartRate;

                    dr["End Balance"] = balance;

                    endbalance = balance;

                    dtResults.Rows.Add(dr);


                    year++;
                    count++;


                    if ((defPeriod == 0) & (payPeriod == 0))
                    { break; }

                }
            }

            
            if (payType != 1)
                totalbenefit = endbalance;

            avgsprate = avgsprate / denom;
            avgcrate = avgcrate / denom;
            
            return dtResults;
        }


        public static double CalculateGuaranteed(double premium, int defPeriod,
            int payPeriod, double guarRate, String payType)
        {

            double guaranteedPayout = 0;
            double balance = 0;

            balance = premium * Math.Pow(1 + guarRate, defPeriod);

            if (payPeriod > 0)
            {
                double benefit;

                double numerator = guarRate * Math.Pow(1 + guarRate, payPeriod);
                double denominator = Math.Pow(1 + guarRate, payPeriod) - 1;

                benefit = balance * (numerator / denominator);

                guaranteedPayout = benefit * payPeriod;
            }

            if (payType == "Lump Sum")
                guaranteedPayout = balance;

            return guaranteedPayout;
        }
        
    } 
}
